home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Softshoe / Lisa's Mac Parts / Windows / Window.cp < prev    next >
Text File  |  2000-06-23  |  8KB  |  358 lines

  1. // Window.cp
  2.  
  3. #ifndef Window_h
  4. #include "Window.h"
  5. #endif
  6. #ifndef WindowDefinition_h
  7. #include "WindowDefinition.h"
  8. #endif
  9. #ifndef WindowUpdater_h
  10. #include "WindowUpdater.h"
  11. #endif
  12. #ifndef MouseDownEvent_h
  13. #include "MouseDownEvent.h"
  14. #endif
  15. #ifndef GraphicsDeviceObject_h
  16. #include "GraphicsDeviceObject.h"
  17. #endif
  18. #ifndef MenuBar_h
  19. #include "MenuBar.h"
  20. #endif
  21. #ifndef WindowInitializer_h
  22. #include "WindowInitializer.h"
  23. #endif
  24. #ifndef Application_h
  25. #include "Application.h"
  26. #endif
  27. #ifndef BroadcastLoop_h
  28. #include "BroadcastLoop.h"
  29. #endif
  30. #ifndef WindowPile_h
  31. #include "WindowPile.h"
  32. #endif
  33. #ifndef WindowLocation_h
  34. #include "WindowLocation.h"
  35. #endif
  36. #ifndef CellClicker_h
  37. #include "CellClicker.h"
  38. #endif
  39. #ifndef CellCursorCollector_h
  40. #include "CellCursorCollector.h"
  41. #endif
  42. #ifndef CellUpdater_h
  43. #include "CellUpdater.h"
  44. #endif
  45. #ifndef RegionObject_h
  46. #include "RegionObject.h"
  47. #endif
  48.  
  49. Window::Window( const WindowDefinition& theDefinition )
  50.   : WindowController( visibility, zoomed, bounds, name, index ),
  51.      Receiver<PreparingToQuit>( PreparingToQuit::TheBroadcaster() ),
  52.      definition( theDefinition ),
  53.      window( theDefinition.Procedure(), theDefinition.Closeable() ),
  54.      pane( window ),
  55.      registration( &window, this ),
  56.      closingLink( focus, *this ),
  57.      visibility( *this, &Window::GetVisibility, &Window::SetVisibility ),
  58.      zoomed( *this, &Window::GetZoomed, &Window::SetZoomed ),
  59.      bounds( *this, &Window::GetBounds, &Window::SetBounds ),
  60.      name( *this, &Window::GetName, &Window::SetName ),
  61.      index( *this, &Window::GetIndex, &Window::SetIndex ),
  62.      controlIdlers( window )
  63.   {
  64.     WindowLocator::Register( registration );
  65.   }
  66.  
  67. Window::~Window()
  68.   {
  69.   }
  70.  
  71. void Window::Initialize( const WindowInitializer& initializer )
  72.   {
  73.     SetName( initializer.NameFor( *this ) );
  74.     
  75.     SetBounds( initializer.PositionFor( *this ) );
  76.  
  77.     if ( initializer.VisibilityFor( *this ) )
  78.       {
  79.         if ( initializer.ZoomOpen() )
  80.           {
  81.             Rectangle destination = window.GlobalBounds();
  82.             destination.Outset( definition.FrameSize() );
  83.             ZoomRects( &initializer.ZoomSource(),
  84.                           &destination,
  85.                           8,
  86.                           kZoomNoAcceleration );
  87.           }
  88.         
  89.         SetIndex( initializer.IndexFor( *this ) );
  90.       }
  91.   }
  92.  
  93. void Window::Update()
  94.   {
  95.     WindowUpdater updater( window );
  96.     pane.Deliver( CellUpdater( window.VisibleRegion() ) );
  97.   }
  98.  
  99. void Window::Activate()
  100.   {
  101.     focus.BeFavored();
  102.     Assert( focus.Active() );
  103.   }
  104.  
  105. void Window::Deactivate()
  106.   {
  107.     focus.BeDisfavored();
  108.     Assert( !focus.Active() );
  109.   }
  110.  
  111. void Window::ClickContent( const MouseDownEvent& event )
  112.   {
  113.     pane.Deliver( CellClicker( event ) );
  114.     
  115.     if ( event.Activating() )
  116.         index.Set( 1 );
  117.   }
  118.  
  119. void Window::ClickDrag( const MouseDownEvent& event )
  120.   {
  121.     if ( event.Activating() && !event.Command() )
  122.         index.Set( 1 );
  123.     
  124.     window.MoveByDragging( event.GlobalPoint() );
  125.     bounds = bounds;            // To help with recording
  126.   }
  127.  
  128. void Window::ClickClose( const MouseDownEvent& event )
  129.   {
  130.     if ( window.TrackCloseBox( event.GlobalPoint() ) )
  131.         Close();
  132.   }
  133.  
  134. void Window::ClickZoomIn( const MouseDownEvent& event )
  135.   {
  136.     if ( window.TrackZoomInBox( event.GlobalPoint() ) )
  137.         zoomed.Set( !GetZoomed() );
  138.   }
  139.  
  140. void Window::ClickZoomOut( const MouseDownEvent& event )
  141.   {
  142.     if ( window.TrackZoomOutBox( event.GlobalPoint() ) )
  143.         zoomed.Set( !GetZoomed() );
  144.   }
  145.  
  146. void Window::ClickGrow( const MouseDownEvent& event )
  147.   {
  148.     PointObject newSize = window.SizeByDragging( event.GlobalPoint(),
  149.                                                                  pane.MinimumSize(),
  150.                                                                  pane.MaximumSize() );
  151.      
  152.      Rectangle newBounds( window.GlobalBounds() );
  153.      newBounds.SetBottomRight( newBounds.TopLeft() + newSize );
  154.      
  155.      bounds.Set( newBounds );
  156.   }
  157.  
  158. const CursorObject& Window::Cursor( const MouseEvent& event,
  159.                                                 RegionObject& sleep )
  160.   {
  161.     CellCursorCollector collector( event, sleep );
  162.     pane.Deliver( collector );
  163.     sleep += Port().LocalToGlobal();
  164.     return collector.Cursor();
  165.   }
  166.  
  167. bool Window::GetVisibility() const
  168.   {
  169.     return window.Visible();
  170.   }
  171.  
  172. void Window::SetVisibility( bool toShow )
  173.   {
  174.     if ( toShow )
  175.         window.Show();
  176.      else
  177.         window.Hide();
  178.   }
  179.  
  180. bool Window::GetZoomed() const
  181.   {
  182.     return window.GlobalBounds() == BestBounds();
  183.   }
  184.  
  185. void Window::SetZoomed( bool toZoom )
  186.   {
  187.     if ( toZoom )
  188.       {
  189.         window.SetStandardBounds( BestBounds() );
  190.         window.ZoomToStandardBounds();
  191.       }
  192.      else
  193.         window.ZoomToUserBounds();
  194.  
  195.     pane.AnnounceSizeChange();
  196.   }
  197.  
  198. Rectangle Window::GetBounds() const
  199.   {
  200.     return window.GlobalBounds();
  201.   }
  202.  
  203. void Window::SetBounds( Rectangle newBounds )
  204.   {
  205.     window.SetBounds( newBounds );
  206.     pane.AnnounceSizeChange();
  207.   }
  208.  
  209. ConstPString Window::GetName() const
  210.   {
  211.     return nameString;
  212.   }
  213.  
  214. void Window::SetName( ConstPString newName )
  215.   {
  216.     nameString = newName;
  217.     window.SetTitle( newName );
  218.   }
  219.  
  220. uint32 Window::GetIndex() const
  221.   {
  222.     return window.Index();
  223.   }
  224.  
  225. void Window::SetIndex( uint32 newIndex )
  226.   {
  227.     window.SetIndex( newIndex );
  228.   }
  229.  
  230. GDHandle Window::DefaultScreen() const
  231.   {
  232.     ::WindowObject *front = ::WindowObject::Front();
  233.     return front == 0
  234.                 ? GraphicsDeviceObject::Main()
  235.                 : front->NearestScreen();
  236.   }
  237.  
  238. Rectangle Window::DefaultPosition( GDHandle screen ) const
  239.   {
  240.     Rectangle available( AvailableArea( screen ) );
  241.     PointObject bestSize = pane.BestSize( available.Size() );
  242.     PointObject reasonableSize = pane.ReasonableSize();
  243.     
  244.     Rectangle bestPile;
  245.     uint32 bestPileScore = maxuint32;
  246.  
  247.     for ( WindowPile pile( available, bestSize );
  248.             pile.Unfinished() && bestPileScore > 0;
  249.             pile++ )
  250.       {
  251.         uint32 score = WindowObject::CountVisibleWindows( *pile );
  252.         
  253.         if ( score >= bestPileScore )
  254.             continue;
  255.  
  256.         bestPileScore = score;
  257.         bestPile = *pile;
  258.       }
  259.         
  260.     PointObject bestLocation;
  261.     uint32 bestLocationScore = maxuint32;
  262.     
  263.     for ( WindowLocation location( bestPile, reasonableSize );
  264.             location.Unfinished() && bestLocationScore > 0;
  265.             location++ )
  266.       {
  267.         Rectangle nearby( *location, *location );
  268.         nearby.Outset( 5 );
  269.         uint32 score = WindowObject::CountVisibleWindows( nearby );
  270.         
  271.         if ( score >= bestLocationScore )
  272.             continue;
  273.  
  274.         bestLocationScore = score;
  275.         bestLocation = *location;
  276.       }
  277.     
  278.     bestSize = pane.BestSize( available.BottomRight() - bestLocation );
  279.  
  280.     return Rectangle( bestLocation, bestLocation + bestSize );
  281.   }
  282.  
  283. bool Window::CanClose() const
  284.   {
  285.     return definition.Closeable();
  286.   }
  287.  
  288. void Window::Close( SavingOption savingOption )
  289.   {
  290.     for ( BroadcastLoop<PreparingToClose> receiver( *this );
  291.             receiver.Unfinished();
  292.             receiver++ )
  293.         receiver->PrepareToClose( savingOption );
  294.     
  295.     window.Hide();
  296.     focus.BeDisfavored();
  297.     delete this;
  298.   }
  299.  
  300. void Window::PrepareToQuit( SavingOption savingOption )
  301.   {
  302.     Close( savingOption );
  303.   }
  304.  
  305. GDHandle Window::BestScreen() const
  306.   {
  307.     return window.NearestScreen();
  308.   }
  309.  
  310. Rectangle Window::BestBounds() const
  311.   {
  312.     return BestBounds( BestScreen() );
  313.   }
  314.  
  315. Rectangle Window::BestBounds( GDHandle screen ) const
  316.   {
  317.     return BestBounds( AvailableArea( screen ) );
  318.   }
  319.  
  320. Rectangle Window::BestBounds( Rectangle available ) const
  321.   {
  322.     Rectangle best( window.GlobalBounds() );
  323.     PointObject bestSize = pane.BestSize( available.Size() );
  324.     
  325.     best.right = best.left + bestSize.h;
  326.     best.bottom = best.top + bestSize.v;
  327.     
  328.     if ( best.right > available.right )
  329.         best += PointObject( available.right - best.right, 0 );
  330.     
  331.     if ( best.bottom > available.bottom )
  332.         best += PointObject( 0, available.bottom - best.bottom );
  333.     
  334.     if ( best.left < available.left )
  335.         best += PointObject( available.left - best.left, 0 );
  336.     
  337.     if ( best.top < available.top )
  338.         best += PointObject( 0, available.top - best.top );
  339.                     
  340.     return best;
  341.   }
  342.  
  343. Rectangle Window::AvailableArea( GDHandle theScreen ) const
  344.   {
  345.     GraphicsDeviceObject screen( theScreen );
  346.     
  347.     Rectangle area( screen.Bounds() );
  348.     
  349.     if ( screen.IsMainScreen() )
  350.         area.top += MenuBar::The().Height();
  351.     
  352.     area.Inset( 3 );
  353.     
  354.     area.Inset( window.FrameSize() );
  355.     
  356.     return area;
  357.   }
  358.